-module(info_ui).

-include_lib("wx/include/wx.hrl").
-include("definitions.hrl").
%% API
-export([start/2, init/1, stop/0, stats/0]).

%% constants
-define(GRID, 2).
-define(BUTTON_START, 1).

-define(RED, {200, 0, 0, 0}).
-define(GREEN, {0, 200, 0, 0}).
-define(BLUE, {0, 0, 200, 0}).

-spec start/2 :: (integer(), node()) -> yes.
start(DeviceCount, Node) ->
  P = spawn(Node, info_ui, init, [DeviceCount]),
  yes = global:register_name(showState, P)
%%    true = register(showState, spawn( info_ui, init, [ServerPid, DeviceCount]))
.

-spec stop/0 :: () -> ok.
stop() ->
  case global:whereis_name(showState) of
    undefined ->
      io:format("showState is already finished~n"),
      ok;
    Pid when is_pid(Pid) ->
      Pid ! {info_ui_stop, self()},
      receive
        info_ui_stopped -> ok
      end
  end.

-spec init/1 :: (integer()) -> true.
init(DeviceCount) ->
  Wx = wx:new(),
  WxStateFrame = wxFrame:new(Wx, -1, "Состояние"),
  wxFrame:setSize(WxStateFrame, {720, 900}),
  Grid = get_grid(WxStateFrame, DeviceCount),
  init_callbacks(WxStateFrame, Grid),
  wxFrame:show(WxStateFrame),
  application:load(ssu2015DeviceTest),
  {ok, Main} = application:get_env(ssu2015DeviceTest, main_node),
  info_updater:start(Main),
  event_loop(WxStateFrame, Grid).

init_callbacks(StateFrame, Grid) ->
  wxFrame:connect(StateFrame, close_window),

  wxGrid:connect(Grid, grid_cell_left_click,
    [
      {userData, {StateFrame, Grid}}
    ]).

-spec stats/0 :: () -> printStats.
stats() ->
  case global:whereis_name(showState) of
    undefined ->
      ok;
    Pid when is_pid(Pid) ->
      Pid ! printStats
  end.

-spec event_loop/2 :: (wxFrame:wxFrame(), wxGrid:wxGrid()) -> true.
event_loop(WxStateFrame, Grid) ->
  receive
    {updateGrid, ListStates, Node, From} when is_list(ListStates) ->
      bind_grid(ListStates, Grid),
      Node, From ! updated_grid,
      event_loop(WxStateFrame, Grid);

    {info_ui_stop, Pid} when is_pid(Pid) ->
      info_updater:stop(),
      io:format("info_ui finished2~n"),
      Pid ! info_ui_stopped,
      true = wxFrame:close(WxStateFrame);

    #wx{event = #wxClose{}} ->
      ok = test_executor_supervisor:stop_executors(),
      info_updater:stop(),
      io:format("info_ui finished1~n"),
      true = wxFrame:close(WxStateFrame);

    printStats ->
      io:format("info_ui got printStats~n"),
      States = storage_supervisor:get_current_states(),
      print_stats(States),
      event_loop(WxStateFrame, Grid);

    Event ->
      case cell_click(Event) of
        true -> ok;
        _ -> io:format("~p: eventLoop: ~p~n", [?MODULE_STRING, Event])
      end,

      event_loop(WxStateFrame, Grid)
  end.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                       работа с гридом
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

-spec cell_click/1 :: (wx()) -> boolean().
%% cell_click(Evt) when (Evt#wx.event)#wxGrid.col =:= 6 ->
cell_click(#wx{userData = {_, Grid}, event = #wxGrid{col = 6, row = Row}}) ->
  DeviceId = list_to_integer(wxGrid:getCellValue(Grid, Row, 2)),
  TestId = list_to_integer(wxGrid:getCellValue(Grid, Row, 1)),
  case test_executor:click(DeviceId, TestId) of
    green -> setGreen(Grid, Row, 6);
    red -> setRed(Grid, Row, 6);
    blue -> setBlue(Grid, Row, 6)
  end,
  true;

cell_click(_) -> false.

-spec get_grid/2 :: (wxFrame:wxFrame(), integer()) -> wxGrid:wxGrid().
get_grid(StateFrame, DeviceCount) ->
  %%Button = wxButton:new(WxStateFrame, ?BUTTON_START, [{label, "SHOW"}, {pos, {30, 30}}, {size, {50, 50}}]),
  Grid = wxGrid:new(StateFrame, ?GRID, [{size, {700, 900}}]),
  Columns = 7,
  wxGrid:createGrid(Grid, DeviceCount, Columns),
  wxGrid:autoSizeRows(Grid),
  wxGrid:autoSizeColumns(Grid),
  wxGrid:setColSize(Grid, 0, 80), %id
  wxGrid:setColSize(Grid, 1, 80), %тест
  wxGrid:setColSize(Grid, 2, 80), %прибор
  wxGrid:setColSize(Grid, 3, 80), %завершен?
  wxGrid:setColSize(Grid, 4, 80), %падал
  wxGrid:setColSize(Grid, 5, 60), %текущий ответ
  wxGrid:setColSize(Grid, 6, 100), %кнопка останова

  wxGrid:setColLabelValue(Grid, 0, "id"),
  wxGrid:setColLabelValue(Grid, 1, "тест"),
  wxGrid:setColLabelValue(Grid, 2, "прибор"),
  wxGrid:setColLabelValue(Grid, 3, "завершен?"),
  wxGrid:setColLabelValue(Grid, 4, "перезапусков"),
  wxGrid:setColLabelValue(Grid, 5, "процент выполнения"),
  wxGrid:setColLabelValue(Grid, 6, "приостановить"),

  paint_grid(Grid, DeviceCount - 1),

  Grid.

-spec paint_grid/2 :: (wxGrid:wxGrid(), integer()) -> ok.
paint_grid(_, -1) ->
  ok;

paint_grid(Grid, CellNumber) ->
  setGreen(Grid, CellNumber, 6), %% кнопка.
  paint_grid(Grid, CellNumber - 1).


-spec bind_grid/2 :: ([state()], wxGrid:wxGrid()) -> ok.
bind_grid(ListStates, Grid) when is_list(ListStates) ->
  foreach(ListStates, Grid, 0),
  ok = wxGrid:refresh(Grid).

-spec foreach/3 :: ([state()], wxGrid:wxGrid(), non_neg_integer()) -> ok.
foreach([], _, _) -> ok;

foreach([State | RestStates], Grid, CurrentIndex) ->
  CellNumber = get_cell_index(Grid, State#stateRecord.id, CurrentIndex),
  wxGrid:setCellValue(Grid, {CellNumber, 0}, integer_to_list(State#stateRecord.id)),
  wxGrid:setCellValue(Grid, {CellNumber, 1}, integer_to_list(State#stateRecord.testId)),
  wxGrid:setCellValue(Grid, {CellNumber, 2}, integer_to_list(State#stateRecord.deviceId)),
  wxGrid:setCellValue(Grid, {CellNumber, 3}, atom_to_list(State#stateRecord.completed)),
  wxGrid:setCellValue(Grid, {CellNumber, 4}, integer_to_list(State#stateRecord.fails)),
  set_percent(Grid, CellNumber, State),
  case State#stateRecord.unexpected_answer of
    true ->
      setRed(Grid, CellNumber, 6);
    false ->
      ok
  end,

  foreach(RestStates, Grid, CurrentIndex + 1).

set_percent(Grid, CellNumber, State) ->
  Percent = length(State#stateRecord.answer) / ?DEFAULT_TEST_LENGTH * 100,
  wxGrid:setCellValue(Grid, {CellNumber, 5}, io_lib:format("~w", [Percent])).

-spec get_cell_index/3 :: (wxGrid:wxGrid(), pos_integer(), integer()) -> integer().
get_cell_index(Grid, StateRecordId, DefaultIndex) ->
  GridRowsCount = wxGrid:getNumberRows(Grid),
  Indexes = [Int || Int <- lists:seq(0, GridRowsCount)],
  List = lists:map(fun(Index) -> get_first_column_value(Grid, Index) end, Indexes),
  Predicate = fun(
      {Id, _
        %RowNumber
      })
    -> StateRecordId == Id end,
  Filtered = lists:filter(Predicate, List),
  N = case Filtered of
        [] -> DefaultIndex;
        NotEmpty when length(NotEmpty) > 0 ->
          {_, Row} = hd(NotEmpty),
          Row
      end,
  N.

-spec get_first_column_value/2 :: (wxGrid:wxGrid(), integer()) -> {integer(), integer()}.
get_first_column_value(Grid, RowNumber) ->
  Id = case wxGrid:getCellValue(Grid, {RowNumber, 0}) of
         [] -> -1;
         List -> list_to_integer(List)
       end,
  {Id, RowNumber}.


setGreen(Grid, Row, Col) ->
  wxGrid:setCellBackgroundColour(Grid, Row, Col, ?GREEN).

setBlue(Grid, Row, Col) ->
  wxGrid:setCellBackgroundColour(Grid, Row, Col, ?BLUE).

setRed(Grid, Row, Col) ->
  wxGrid:setCellBackgroundColour(Grid, Row, Col, ?RED).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                       статистика
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

-spec print_stats/1 :: ([state()]) -> no_return().
print_stats(States) ->
  SumThreads = fun(#stateRecord{fails = FailsCount, completed = Completed}, FailsTotal)
    -> case Completed of
         true ->
           FailsCount + FailsTotal + 1;%% успешное завершение не записывается в падения
         false ->
           FailsCount + FailsTotal
       end
  end,
  KilledThreads1 = lists:foldl(SumThreads, 0, States),
  io:format("Killed threads: ~w~n", [KilledThreads1]),
  io:format("Devices: ~w~n", [length(States)]).